package com.shuda.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shuda.common.exception.BusinessException;
import com.shuda.common.utils.SecurityUtils;
import com.shuda.system.dto.UserRoleDTO;
import com.shuda.system.entity.RoleEntity;
import com.shuda.system.entity.UserEntity;
import com.shuda.system.entity.UserRoleEntity;
import com.shuda.system.mapper.RoleMapper;
import com.shuda.system.mapper.UserMapper;
import com.shuda.system.mapper.UserRoleMapper;
import com.shuda.system.service.UserRoleService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户角色关联服务实现类
 */
@Service
public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRoleEntity> implements UserRoleService {

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Override
    public List<UserRoleDTO> getUserRoles(Long userId) {
        LambdaQueryWrapper<UserRoleEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRoleEntity::getUserId, userId)
                .eq(UserRoleEntity::getDeleted, 0);

        List<UserRoleEntity> entities = userRoleMapper.selectList(wrapper);
        return entities.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void assignUserRoles(Long userId, List<Long> roleIds) {
        // 先删除现有角色关联
        LambdaQueryWrapper<UserRoleEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRoleEntity::getUserId, userId);
        userRoleMapper.delete(wrapper);

        // 添加新的角色关联
        if (roleIds != null && !roleIds.isEmpty()) {
            for (Long roleId : roleIds) {
                // 验证角色是否存在
                RoleEntity role = roleMapper.selectById(roleId);
                if (role == null || role.getDeleted() == 1) {
                    throw new BusinessException("角色不存在或已删除：" + roleId);
                }

                UserRoleEntity userRoleEntity = new UserRoleEntity();
                userRoleEntity.setUserId(userId);
                userRoleEntity.setRoleId(roleId);
                userRoleEntity.setCreateBy(SecurityUtils.getCurrentUsername());
                userRoleEntity.setCreateTime(LocalDateTime.now());
                userRoleEntity.setUpdateBy(SecurityUtils.getCurrentUsername());
                userRoleEntity.setUpdateTime(LocalDateTime.now());
                userRoleEntity.setDeleted(0);
                userRoleMapper.insert(userRoleEntity);
            }
        }
    }

    @Override
    @Transactional
    public void removeUserRole(Long userId, Long roleId) {
        LambdaQueryWrapper<UserRoleEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRoleEntity::getUserId, userId)
                .eq(UserRoleEntity::getRoleId, roleId);
        userRoleMapper.delete(wrapper);
    }

    @Override
    public List<UserRoleDTO> getRoleUsers(Long roleId) {
        LambdaQueryWrapper<UserRoleEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRoleEntity::getRoleId, roleId)
                .eq(UserRoleEntity::getDeleted, 0);

        List<UserRoleEntity> entities = userRoleMapper.selectList(wrapper);
        return entities.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void batchAssignUserRoles(List<Long> userIds, Long roleId) {
        if (userIds != null && !userIds.isEmpty()) {
            // 验证角色是否存在
            RoleEntity role = roleMapper.selectById(roleId);
            if (role == null || role.getDeleted() == 1) {
                throw new BusinessException("角色不存在或已删除：" + roleId);
            }

            for (Long userId : userIds) {
                // 检查是否已存在关联
                LambdaQueryWrapper<UserRoleEntity> checkWrapper = new LambdaQueryWrapper<>();
                checkWrapper.eq(UserRoleEntity::getUserId, userId)
                        .eq(UserRoleEntity::getRoleId, roleId);
                
                if (userRoleMapper.selectCount(checkWrapper) == 0) {
                    UserRoleEntity userRoleEntity = new UserRoleEntity();
                    userRoleEntity.setUserId(userId);
                    userRoleEntity.setRoleId(roleId);
                    userRoleEntity.setCreateBy(SecurityUtils.getCurrentUsername());
                    userRoleEntity.setCreateTime(LocalDateTime.now());
                    userRoleEntity.setUpdateBy(SecurityUtils.getCurrentUsername());
                    userRoleEntity.setUpdateTime(LocalDateTime.now());
                    userRoleEntity.setDeleted(0);
                    userRoleMapper.insert(userRoleEntity);
                }
            }
        }
    }

    @Override
    @Transactional
    public void batchRemoveUserRoles(List<Long> userIds, Long roleId) {
        if (userIds != null && !userIds.isEmpty()) {
            LambdaQueryWrapper<UserRoleEntity> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(UserRoleEntity::getUserId, userIds)
                    .eq(UserRoleEntity::getRoleId, roleId);
            userRoleMapper.delete(wrapper);
        }
    }

    private UserRoleDTO convertToDTO(UserRoleEntity entity) {
        UserRoleDTO dto = new UserRoleDTO();
        BeanUtils.copyProperties(entity, dto);

        // 查询用户信息
        UserEntity user = userMapper.selectById(entity.getUserId());
        if (user != null) {
            dto.setUsername(user.getUsername());
        }

        // 查询角色信息
        RoleEntity role = roleMapper.selectById(entity.getRoleId());
        if (role != null) {
            dto.setRoleName(role.getRoleName());
            dto.setRoleCode(role.getRoleCode());
        }

        return dto;
    }
}